# -*- coding: utf-8 -*-
# @Date    : 2021/11/2 17:12
# @File    : web_robot.py
# @User    : zhensu2

import time

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from config.global_settings import CHROME_PATH, DEFAULT_WAIT


class OriginalRobot:
    def __init__(self, url, download_path):
        self.url = url

        """
        ChromeOptions是chromedriver支持的浏览器启动选项。
        options常用属性及方法为：
        binary_location = ''：指定Chrome浏览器路径
        debuger_address = '：指定调试路径
        headless: 无界面模式
        add_argument()：添加启动参数
        add_extension：添加本地插件
        add_experimental_option：添加实验选项
        to_capablilities：将options转为标准的capablitiies格式      
        """
        chromeOptions = webdriver.ChromeOptions()
        self.download_path = download_path
        # 定义一个字典
        prefs = {"download.default_directory": self.download_path,
                 "profile.default_content_setting_values.automatic_downloads": 1,
                 'download.prompt_for_download': False
                 }
        # 添加实验选项
        chromeOptions.add_experimental_option("prefs", prefs)

        self.driver = webdriver.Chrome(chrome_options=chromeOptions, executable_path=CHROME_PATH)

        # self.driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')
        # params = {'cmd': 'Page.setDownloadBehavior',
        #           'params': {'behavior': 'allow', 'downloadPath': self.download_path}}
        # self.driver.execute("send_command", params)

        self.driver.maximize_window()


    def click_element(self, xpath, timeout=DEFAULT_WAIT, mode='internal'):
        """
        点击元素
        :param mode: 点击元素的模式
        :param xpath: xpath
        :param timeout: 等待元素出现时间，若超时则报错
        :return: None
        """
        """
        WebDriverWait()：显示等待，同样也是webdirver提供的方法。在设置时间内，默认每隔一段时间检测一次当前页面元素是否存在，
        如果超过设置时间检测不到则抛出异常。默认检测频率为0.5s，默认抛出异常为：NoSuchElementException
        driver: 传入WebDriver实例，即我们上例中的driver
        timeout: 超时时间，等待的最长时间（同时要考虑隐性等待时间）
        poll_frequency: 调用until或until_not中的方法的间隔时间，默认是0.5秒
        ignored_exceptions: 忽略的异常，如果在调用until或until_not的过程中抛出这个元组中的异常，
        则不中断代码，继续等待，如果抛出的是这个元组外的异常，则中断代码，抛出异常。默认只有NoSuchElementException。
        原文链接：https://blog.csdn.net/zzhangsiwei/article/details/115056377
        until
        method: 在等待期间，每隔一段时间（__init__中的poll_frequency）调用这个传入的方法，直到返回值不是Falsemessage: 如果超时，
        抛出TimeoutException，将message传入异常
        until_not     
        与until相反，until是当某元素出现或什么条件成立则继续执行， until_not是当某元素消失或什么条件不成立则继续执行，参数也相同，不再赘述。
        """
        element_located = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=0.5).until(
            EC.presence_of_element_located((By.XPATH, xpath))
        )
        if mode == 'internal':
            element = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=0.5).until(
                EC.element_to_be_clickable((By.XPATH, xpath))
            )
            element.click()
        elif mode == 'external':
            self.driver.execute_script("$(arguments[0]).click()", element_located)

    def fill_input(self, xpath, content, timeout=DEFAULT_WAIT):
        """
        填写网页表单
        :param xpath: xpath
        :param content: 填写内容
        :param timeout: 等待元素出现时间，若超时则报错
        :return:
        """
        element = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=0.5).until(
            EC.presence_of_element_located((By.XPATH, xpath))
        )
        self.click_element(xpath, timeout=timeout)
        element.send_keys(content)

    def find_element(self, xpath, timeout=DEFAULT_WAIT):
        """
        通过xpath寻找元素，并返回元素对象
        :param xpath: xpath
        :param timeout: 等待元素出现时间，若超时则报错
        :return:
        selenium等待presence_of_element_located
        页面元素等待处理。
        """
        element = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=0.5).until(
            EC.presence_of_element_located((By.XPATH, xpath))
        )
        return element

    def find_elements(self, xpath, timeout=DEFAULT_WAIT):
        """
        通过xpath去寻找所有元素，返回多个元素对象
        :param xpath: xpath
        :param timeout: 等待元素出现时间，若超时则报错
        :return:
        """
        elements = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=0.5).until(
            EC.presence_of_all_elements_located((By.XPATH, xpath))
        )
        return elements

    # def get_verification_code(self, xpath):
    #     """
    #     获取验证码值
    #     :param xpath: 验证码图片xpath
    #     :return:
    #     """
    #     element = self.find_element(xpath)
    #     img_base64 = element.screenshot_as_base64
    #
    #     import ddddocr
    #     ocr = ddddocr.DdddOcr()
    #     res = ocr.classification(img_base64)
    #     return res

    def switch_window(self, position=-1):
        """
        切换浏览器窗口
        :param position: 默认为-1，即最新的窗口
        :return:
        """
        windows = self.driver.window_handles
        self.driver.switch_to.window((windows[position]))

    def element_exist(self, xpath, timeout):
        """
        判断元素在timeout时间内是否存在，若不存在则返回False，反之True
        :param xpath: xpath
        :param timeout: 等待元素出现时间
        :return: True/False
        """
        try:
            _ = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=0.5).until(
                EC.presence_of_element_located((By.XPATH, xpath))
            )
            return True
        except:
            return False
